/*
	Copyright 2008 Jay Elliott

	This file is part of libemath.

	libemath is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	libemath is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with libemath.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef __CPOINT3D_H_
#define __CPOINT3D_H_

#include <cmath>
#include <cstdio>

#include "macros.h"

namespace emath
{

class cPoint3d
{
public:
	float x, y, z, w;//w is really only there so that the matrix multiplication works right.

	inline cPoint3d(void);//intiales to (0, 0, 0), and w = 1
	inline cPoint3d(const float vert[3]);
	inline cPoint3d(float xCoord, float yCoord, float zCoord);
	
	inline cPoint3d normalize(void) const;
	inline float GetMag(void) const;
	
	inline float dot(cPoint3d other) const;

	inline cPoint3d operator-(const cPoint3d& other) const;

	inline cPoint3d cross(const cPoint3d& other) const;

	inline cPoint3d interpolate(cPoint3d end, float t);

	float& operator[](unsigned index);
	inline cPoint3d operator+(cPoint3d other) const;
	inline cPoint3d operator+(float scalar) const;
	inline cPoint3d operator-(float scalar) const;
	bool operator==(const cPoint3d& other) const;
};

inline emath::cPoint3d operator*(cPoint3d vect, float scalar);
inline emath::cPoint3d operator*(float scalar, cPoint3d vect);


/*************************************
*
*
*	inline function definitions
*
*
***************************************/



cPoint3d::cPoint3d(void)
{
	x = y = z = 0.0f;

	w = 1.0f;
}

cPoint3d::cPoint3d(const float vert[3])
{
	x = vert[0];
	y = vert[1];
	z = vert[2];
}

cPoint3d::cPoint3d(float xCoord, float yCoord, float zCoord)
{
	x = xCoord;
	y = yCoord;
	z = zCoord;
	w = 1.0f;
}

float cPoint3d::GetMag(void) const
{
	return sqrt(x * x + y * y + z * z);
}

cPoint3d cPoint3d::normalize(void) const
{
	cPoint3d ret;

	float mag = GetMag();

	ret.x = x / mag;
	ret.y = y / mag;
	ret.z = z / mag;

	return ret;
}

cPoint3d cPoint3d::operator-(const cPoint3d& other) const
{
	cPoint3d ret;

	ret.x = x - other.x;
	ret.y = y - other.y;
	ret.z = z - other.z;

	return ret;
}

cPoint3d cPoint3d::cross(const cPoint3d& other) const
{
	cPoint3d ret;

	ret.x = y * other.z - z * other.y;
	ret.y = z * other.x - x * other.z;
	ret.z = x * other.y - y * other.x;

	return ret;
}

cPoint3d cPoint3d::interpolate(cPoint3d end, float t)
{
	cPoint3d ret;

	ret.x = x + t * (end.x - x);
	ret.y = y + t * (end.y - y);
	ret.z = z + t * (end.z - z);

	return ret;
}

cPoint3d operator*(cPoint3d vect, float scalar)
{
	return cPoint3d(vect.x * scalar, vect.y * scalar, vect.z * scalar);
}

cPoint3d operator*(float scalar, cPoint3d vect)
{
	return cPoint3d(vect.x * scalar, vect.y * scalar, vect.z * scalar);
}

cPoint3d cPoint3d::operator+(cPoint3d other) const
{
	return cPoint3d(x + other.x, y + other.y, z + other.z);
}

float cPoint3d::dot(cPoint3d other) const
{
	return x * other.x + y * other.y + z * other.z;
}

cPoint3d cPoint3d::operator+(float scalar) const
{
	return cPoint3d(x + scalar, y + scalar, z + scalar);
}

cPoint3d cPoint3d::operator-(float scalar) const
{
	return cPoint3d(x - scalar, y - scalar, z - scalar);
}


}

#endif
